home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 21 / Mac Magazin and MacEasy Magazine CD - Issue 21.iso / Wissenschaft & Technik / yorick12vr1-nofpu folder / include / plwf.i < prev    next >
Text File  |  1996-02-13  |  6KB  |  188 lines

  1. /*
  2.    PLWF.I
  3.    Simple "painter's algorithm"-class routine for making 3-D wire frames
  4.    and related models.
  5.  
  6.    $Id$
  7.  */
  8. /*    Copyright (c) 1996.  The Regents of the University of California.
  9.                     All rights reserved.  */
  10.  
  11. require, "pl3d.i";
  12.  
  13. func plwf(z,y,x, fill=,shade=,edges=,ecolor=,ewidth=,cull=,scale=,cmax=)
  14. /* DOCUMENT plwf, z
  15.          or plwf, z, y,x
  16.  
  17.      plots a 3-D wire frame of the given Z array, which must have the
  18.      same dimensions as the mesh (X, Y).  If X and Y are not given, they
  19.      default to the first and second indices of Z, respectively.
  20.      The drawing order of the zones is determined by a simple "painter's
  21.      algorithm", which works fairly well if the mesh is reasonably near
  22.      rectilinear, but can fail even then if the viewpoint is chosen to
  23.      produce extreme fisheye perspective effects.  Look at the resulting
  24.      plot carefully to be sure the algorithm has correctly rendered the
  25.      model in each case.
  26.  
  27.    KEYWORDS: fill   -- optional colors to use (default is to make zones
  28.                        have background color), same dimension options as
  29.                        for z argument to plf function
  30.          shade  -- set non-zero to compute shading from current
  31.                    3D lighting sources
  32.              edges  -- default is 1 (draw edges), but if you provide fill
  33.                        colors, you may set to 0 to supress the edges
  34.              ecolor, ewidth  -- color and width of edges
  35.          cull   -- default is 1 (cull back surfaces), but if you want
  36.                    to see the "underside" of the model, set to 0
  37.          scale  -- by default, Z is scaled to "reasonable" maximum
  38.                    and minimum values related to the scale of (X,Y).
  39.                This keyword alters the default scaling factor, in
  40.                the sense that scale=2.0 will produce twice the
  41.                Z-relief of the default scale=1.0.
  42.          cmax   -- the ambient= keyword in light3 can be used to
  43.                    control how dark the darkest surface is; use this
  44.                to control how light the lightest surface is
  45.                the lightwf routine can change this parameter
  46.                interactively
  47.  
  48.    SEE ALSO: lightwf, plm, plf, orient3, light3, fma3, window3
  49.  */
  50. {
  51.   if (_draw3) {
  52.     xyz= _nxt(z);
  53.     fill= _nxt(z);
  54.     shade= _nxt(z);
  55.     edges= _nxt(z);
  56.     ecolor= _nxt(z);
  57.     ewidth= _nxt(z);
  58.     cull= _nxt(z);
  59.     cmax= _nxt(z);
  60.  
  61.     get3_xy, xyz, x, y, z, 1;
  62.  
  63.     /* rotate (x,y,0) into on-screen orientation to determine order
  64.      * just use four corners for this */
  65.     nx= dimsof(x);
  66.     ny= nx(3);
  67.     nx= nx(2);
  68.     xyzc= xyz(,1:nx:nx-1,1:ny:ny-1);
  69.     xyzc(3,,)= 0.0;
  70.     get3_xy, xyzc, xc, yc, zc, 1;
  71.  
  72.     /* compute mean i-edge and j-edge vector z-components */
  73.     iedge= avg(zc(0,)-zc(1,));
  74.     jedge= avg(zc(,0)-zc(,1));
  75.  
  76.     /* compute shading if necessary */
  77.     if (shade) {
  78.       xyz(1,,)= x;
  79.       xyz(2,,)= y;
  80.       xyz(3,,)= z;
  81.       fill= get3_light(xyz);
  82.     }
  83.  
  84.     /* The order either requires a transpose or not, reversal of the
  85.        order of the first dimension or not, and reversal of the order
  86.        of the second dimension or not.  */
  87.  
  88.     /* The direction with the minimum magnitude average z-component must
  89.        vary fastest in the painting order.  If this is the j-direction,
  90.        a transpose will be required to make this the i-direction.  */
  91.     if (abs(jedge)<abs(iedge)) {
  92.       tmp= iedge;   iedge= jedge;   jedge= tmp;
  93.       x= transpose(x);
  94.       y= transpose(y);
  95.       if (!is_void(fill)) fill= transpose(fill);
  96.     }
  97.  
  98.     /* Zones must be drawn from back to front, which means that the
  99.        average z-component of the edge vectors must be positive.  This
  100.        can be arranged by reversing the order of the elements if
  101.        necessary.  */
  102.     if (iedge<0.0) {
  103.       x= x(::-1,);
  104.       y= y(::-1,);
  105.       if (!is_void(fill)) fill= fill(::-1,);
  106.     }
  107.     if (jedge<0.0) {
  108.       x= x(,::-1);
  109.       y= y(,::-1);
  110.       if (!is_void(fill)) fill= fill(,::-1);
  111.     }
  112.  
  113.     plf, fill, y,x, edges=edges,ecolor=ecolor,ewidth=ewidth,
  114.       cmin=0.0,cmax=cmax,legend=string(0);
  115.     return;
  116.   }
  117.  
  118.   xyz= xyz_wf(z, y, x, scale=scale);
  119.  
  120.   if (is_void(edges)) edges= 1;
  121.   if (is_void(shade)) shade= 0;
  122.   else if (!is_void(fill))
  123.     error, "specify either fill or shade, not both";
  124.  
  125.   clear3;
  126.   set3_object, plwf,
  127.     _lst(xyz, fill, shade, edges, ecolor, ewidth, cull, cmax);
  128. }
  129.  
  130. func lightwf(cmax)
  131. /* DOCUMENT lightwf, cmax
  132.      Sets the cmax= parameter interactively, assuming the current
  133.      3D display list contains the result of a previous plwf call.
  134.      This changes the color of the brightest surface in the picture.
  135.      The darkest surface color can be controlled using the ambient=
  136.      keyword to light3.
  137.    SEE ALSO: plwf, light3
  138.  */
  139. {
  140.   list= _cdr(_draw3_list, _draw3_n);
  141.   if (_car(list)!=plwf) error, "current 3D display list is not a plwf";
  142.   _undo3_set, lightwf, _car(_car(list,2), 8, cmax);
  143. }
  144.  
  145. /* The function which scales the "topography" of z(x,y) is
  146.  * potentially useful apart from plwf.
  147.  * For example, the xyz array used by plwf can be converted from
  148.  * a quadrilateral mesh plotted using plf to a polygon list plotted
  149.  * using plfp like this:
  150.  *   xyz= xyz_wf(z,y,x,scale=scale);
  151.  *   ni= dimsof(z)(2);
  152.  *   nj= dimsof(z)(3);
  153.  *   list= indgen(1:ni-1)+ni*indgen(0:nj-2)(-,);
  154.  *   xyz= xyz(,([0,1,ni+1,ni]+list(-,))(*));
  155.  *   nxyz= array(4, (ni-1)*(nj-1));
  156.  */
  157. func xyz_wf(z, y, x, scale=)
  158. {
  159.   if (min(dimsof(z))<2) error, "impossible dimensions for z array";
  160.   if (is_void(y) || is_void(x)) {
  161.     if (!is_void(y) || !is_void(x)) error, "either give y,x both or neither";
  162.     nx= dimsof(z)(2);
  163.     ny= dimsof(z)(3);
  164.     x= span(1,nx,nx)(,-:1:ny);
  165.     y= span(1,ny,ny)(-:1:nx,);
  166.   } else if (anyof(dimsof(x)!=dimsof(z)) ||
  167.          anyof(dimsof(x)!=dimsof(z))) {
  168.     error, "x, y, and z must all have same dimensions";
  169.   }
  170.  
  171.   xyscl= double(max(max(x)-min(x),max(y)-min(y)));
  172.   if (!is_void(scale)) xyscl*= scale;
  173.   dz= double(max(z)-min(z));
  174.   /* zbar= abs(avg(z));
  175.    * zscl= max(dz,zbar); */
  176.   zscl= dz + (dz==0.0);
  177.   if (zscl) z*= 0.5*xyscl/zscl;
  178.  
  179.   xyz= array(0.0, 3,dimsof(z));
  180.   xyz(1,,)= x;
  181.   xyz(2,,)= y;
  182.   xyz(3,,)= z;
  183.  
  184.   /* put center of mesh at (0,0,0) */
  185.   xyz-= xyz(,avg,avg);
  186.   return xyz;
  187. }
  188.